﻿///////////////////////////////////////////////////////
//
// XDesigner.ORM 
//
// autohr : yuans
//
// date: 2011-2-23
//
// email  : yyf9989@hotmail.com
// 
//
///////////////////////////////////////////////////////
using System;
using System.Text;
using System.Reflection;

namespace XDesigner.ORM
{
    public class CollectionTypeHelper
    {
        private static System.Collections.Hashtable myCollectionElementTypes
            = new System.Collections.Hashtable();
        /// <summary>
        /// 判断指定类型是否是列表类型
        /// </summary>
        /// <param name="ObjectType">对象类型</param>
        /// <returns>若是列表类型则返回列表成员类型,否则返回空引用</returns>
        public static bool IsCollectionType(Type ObjectType)
        {
            if (ObjectType == null)
            {
                throw new ArgumentNullException("ObjectType");
            }
            return GetElementType(ObjectType) != null;
        }

        public static Type GetElementType(Type CollectionType)
        {
            if (CollectionType == null)
            {
                throw new ArgumentNullException("ObjectType");
            }
            if (CollectionType.Equals(typeof(string)))
                return null;
            if (CollectionType.IsSubclassOf(typeof(Array)))
                return null;
            if (myCollectionElementTypes.ContainsKey(CollectionType))
                return (Type)myCollectionElementTypes[CollectionType];

            Type[] interfaces = CollectionType.GetInterfaces();
            bool find = false;
            foreach (Type t in interfaces)
            {
                if (t.Equals(typeof(System.Collections.IEnumerable))
                    || t.IsSubclassOf(typeof(System.Collections.IEnumerable)))
                {
                    find = true;
                    break;
                }
            }
            if (find)
            {
                System.Reflection.MethodInfo method = GetAddMethod(CollectionType);
                if (method != null)
                {
                    Type t = method.GetParameters()[0].ParameterType;
                    myCollectionElementTypes[CollectionType] = t;
                    return t;
                }
            }
            myCollectionElementTypes[CollectionType] = null;
            return null;
        }

        private static System.Collections.Hashtable myAddMethods
            = new System.Collections.Hashtable();
        /// <summary>
        /// 获得指定列表类型的Add 方法
        /// </summary>
        /// <param name="t">类型</param>
        /// <returns>方法信息对象</returns>
        public static System.Reflection.MethodInfo GetAddMethod(Type CollectionType)
        {
            if (CollectionType == null)
            {
                throw new ArgumentNullException("CollectionType");
            }
            if (myAddMethods.ContainsKey(CollectionType))
            {
                return (System.Reflection.MethodInfo)myAddMethods[CollectionType];
            }
            System.Reflection.MemberInfo[] dms = CollectionType.GetDefaultMembers();
            Type ElementType = null;
            if (dms != null && dms.Length > 0)
            {
                foreach (System.Reflection.MemberInfo m in dms)
                {
                    if (m is System.Reflection.PropertyInfo)
                    {
                        ElementType = ((System.Reflection.PropertyInfo)m).PropertyType;
                        break;
                    }
                }
            }
            System.Reflection.MethodInfo[] ms = CollectionType.GetMethods(
                BindingFlags.Public
                | BindingFlags.Instance
                | BindingFlags.DeclaredOnly);
            foreach (System.Reflection.MethodInfo m in ms)
            {
                if (m.Name == "Add")
                {
                    System.Reflection.ParameterInfo[] ps = m.GetParameters();
                    if (ps != null && ps.Length == 1)
                    {
                        if (ElementType != null)
                        {
                            if (ps[0].ParameterType.Equals(ElementType)
                                || ps[0].ParameterType.IsSubclassOf(ElementType))
                            {
                                myAddMethods[CollectionType] = m;
                                return m;
                            }
                        }
                        else
                        {
                            myAddMethods[CollectionType] = m;
                            return m;
                        }
                    }//if
                }//if
            }//foreach
            return null;
        }
    }
}
